using System;
using System.Drawing;
using System.Drawing.Imaging;
using System.Runtime.InteropServices;
using System.Collections;
using System.Collections.Generic;
using System.Windows.Forms;
using System.Data;
using System.Diagnostics;
using System.IO;
using System.Reflection;
using System.Runtime.Serialization;
using System.Runtime.Serialization.Formatters.Binary;
using System.Resources;
using ObjectLib;
using EngMATLib;
using FftLib;
using BmgNet;
using StaticUtility;

namespace ObjectParser
{
    public class SelectionRecord
    {
        public CategoryNode CnPix=null;
        public CategoryNode Cn=null;
        public ParsedObject Po=null;
        public PolygonF Poly=null;
        public ContourF Con=null;
        public Circle Roi;
        public object SelThing=null;
        public TreeNode SelNode=null;
        public FormParse Parser;
        public SelectionRecord(object SelThing, FormParse Parser)
        {
            this.Parser = Parser;
            if(SelThing!=null)
            {
                if(SelThing.GetType()==typeof(TreeNode))
                {
                    this.SelNode = (TreeNode)SelThing;
                    this.SelThing = SelNode.Tag;
                }
                else
                {
                    this.SelNode = Parser.NodeAttachedTo(SelThing);
                    this.SelThing = SelThing;
                }
                if(SelThing.GetType()==typeof(Circle))
                    Roi = (Circle)SelThing;
                else if(SelThing.GetType()==typeof(ContourF))
                {
                    Con = (ContourF)SelThing;
                    Poly = Con.PolyOwner;
                    Po = Poly.Owner;
                    Cn = Po.Category;
                    CnPix = Cn.PixExcludeNode;
                }
                else if(SelThing.GetType()==typeof(PolygonF))
                {
                    Poly = (PolygonF)SelThing;
                    Po = Poly.Owner;
                    Cn = Po.Category;
                    CnPix = Cn.PixExcludeNode;
                }
                else if(SelThing.GetType()==typeof(ParsedObject))
                {
                    Po = (ParsedObject)SelThing;
                    Cn = Po.Category;
                    CnPix = Cn.PixExcludeNode;
                }
                else if(SelThing.GetType()==typeof(CategoryNode))
                {
                    Cn = (CategoryNode)SelThing;
                    CnPix = Cn.PixExcludeNode;
                }
            }
        }
        public bool IsEqual(SelectionRecord other)
        {
            return this.SelThing == other.SelThing;
        }
        public static void UpdateBitmaps(SelectionRecord past,SelectionRecord present,FormParse parser)
        {
            if(past.CnPix != present.CnPix)
            {
                ClearBitmaps(past.CnPix,past,parser);
                PaintBitmaps(present.CnPix,present,parser);
            }
            else if(past.Cn != present.Cn)
            {
                ClearBitmaps(past.Cn,past,parser);
                ClearBitmaps(present.Cn,past,parser);
                PaintBitmaps(past.Cn,present,parser);
                PaintBitmaps(present.Cn,present,parser);
            }
            else if(past.Po != present.Po)
            {
                ClearBitmaps(past.Po,past,parser);
                ClearBitmaps(present.Po,past,parser);
                PaintBitmaps(past.Po,present,parser);
                PaintBitmaps(present.Po,present,parser);
            }
            else if(past.Poly != present.Poly)
            {
                ClearBitmaps(past.Poly,past,parser);
                ClearBitmaps(present.Poly,past,parser);
                PaintBitmaps(past.Poly,present,parser);
                PaintBitmaps(present.Poly,present,parser);
            }
        }
        /// <summary>
        /// Clears bitmaps of the object o.
        /// </summary>
        /// <param name="o">object ( CategoryNode or ParsedObject or PolygonF )</param>
        /// <param name="clip">Rectangle  The clipping rectangle in Img coordinates.  You may set this value to null for no clip rect.</param>
        public static void ClearBitmaps(object o, SelectionRecord sel, FormParse parser)
        {
            if(o != null)
            {
                if(o.GetType()==typeof(CategoryNode))
                {
                    CategoryNode cn = (CategoryNode)o;
                    //	Get rid of the objects at the current level.
                    for(int i=0;i<cn.Objects.Count;i++)
                        ClearBitmaps(cn.Objects[i],sel,parser);

                    //	Get rid of the objects in lower level nodes.
                    for(int i=0;i<cn.Sub.Count;i++)
                        ClearBitmaps(cn.Sub[i],sel,parser);
                }
                else if(o.GetType()==typeof(ParsedObject))
                {
                    ParsedObject po = (ParsedObject)o;
                    if(po == sel.Po)
                    {
                        for(int i=0;i<po.Polygons.Count;i++)
                            if(po.Polygons[i]!=sel.Poly)
                                Imprint(parser.BmpCurrentObj,Color.Transparent,po.Polygons[i].Pix,false);
                    }
                    else if(po.Category == sel.Cn)
                        for(int i=0;i<po.Polygons.Count;i++)
                            Imprint(parser.BmpOtherObj,Color.Transparent,po.Polygons[i].Pix,false);
                    else if(po.Category.PixExcludeNode == sel.CnPix)
                        for(int i=0;i<po.Polygons.Count;i++)
                            Imprint(parser.BmpNonObj,Color.Transparent,po.Polygons[i].Pix,false);
                }
                else if(o.GetType()==typeof(PolygonF))
                {
                    PolygonF pf = (PolygonF)o;
                    //	clear active poly when bViewActiveCat is fully selected
                    if(pf != sel.Poly)
                    {
                        if(pf.Owner == sel.Po)
                            Imprint(parser.BmpCurrentObj,Color.Transparent,pf.Pix,false);
                        else if(pf.Owner.Category == sel.Cn)
                            Imprint(parser.BmpOtherObj,Color.Transparent,pf.Pix,false);
                        else if(pf.Owner.Category.PixExcludeNode == sel.CnPix)
                            Imprint(parser.BmpNonObj,Color.Transparent,pf.Pix,false);
                    }
                }
            }
        }
        /// <summary>
        /// Paints bitmaps with the object o.
        /// </summary>
        /// <param name="o">object ( CategoryNode or ParsedObject or PolygonF )</param>
        /// <param name="clip">Rectangle  The clipping rectangle in Img coordinates.  You may set this value to null for no clip rect.</param>
        public static void PaintBitmaps(object o,SelectionRecord sel, FormParse parser)
        {
            if(o != null)
            {
                if(o.GetType()==typeof(CategoryNode))
                {
                    CategoryNode cn = (CategoryNode)o;
                    //	Get rid of the objects at the current level.
                    for(int i=0;i<cn.Objects.Count;i++)
                        PaintBitmaps(cn.Objects[i],sel,parser);

                    //	Get rid of the objects in lower level nodes.
                    for(int i=0;i<cn.Sub.Count;i++)
                        PaintBitmaps(cn.Sub[i],sel,parser);
                }
                else if(o.GetType()==typeof(ParsedObject))
                {
                    ParsedObject po = (ParsedObject)o;
                    if(po == sel.Po)
                    {
                        for(int i=0;i<po.Polygons.Count;i++)
                            if(po.Polygons[i]!=sel.Poly)
                                Imprint(parser.BmpCurrentObj,parser.Opd.ObjCurrColor,po.Polygons[i].Pix,false);
                    }
                    else if(po.Category == sel.Cn)
                        for(int i=0;i<po.Polygons.Count;i++)
                            Imprint(parser.BmpOtherObj,parser.Opd.ObjOtherColor,po.Polygons[i].Pix,false);
                    else if(po.Category.PixExcludeNode == sel.CnPix)
                        for(int i=0;i<po.Polygons.Count;i++)
                            Imprint(parser.BmpNonObj,parser.Opd.ObjNonColor,po.Polygons[i].Pix,false);
                }
                else if(o.GetType()==typeof(PolygonF))
                {
                    PolygonF pf = (PolygonF)o;
                    //	paint active poly when bViewActiveCat is fully selected
                    if(pf != sel.Poly)
                    {
                        if(pf.Owner == sel.Po)
                            Imprint(parser.BmpCurrentObj,parser.Opd.ObjCurrColor,pf.Pix,false);
                        else if(pf.Owner.Category == sel.Cn)
                            Imprint(parser.BmpOtherObj,parser.Opd.ObjOtherColor,pf.Pix,false);
                        else if(pf.Owner.Category.PixExcludeNode == sel.CnPix)
                            Imprint(parser.BmpNonObj,parser.Opd.ObjNonColor,pf.Pix,false);
                    }
                }
            }
        }
        /// <summary>
        /// Imprints pix onto bmp using the Color c.
        /// </summary>
        /// <param name="bmp"></param>
        /// <param name="c"></param>
        /// <param name="pix"></param>
        public static void Imprint(Bitmap bmp,Color c,PixelTagger pix,Rectangle clip)
        {
            if(bmp!=null && pix!=null)
            {
                int left = Math.Max(0,Math.Max(pix.Left,clip.Left));
                int right = Math.Min(bmp.Width-1,Math.Min(pix.Right,clip.Right));
                int top = Math.Max(0,Math.Max(pix.Top,clip.Top));
                int bottom = Math.Min(bmp.Height-1,Math.Min(pix.Bottom,clip.Bottom));

                unsafe
                {
                    BitmapData bd = bmp.LockBits(new Rectangle(0,0,bmp.Width,bmp.Height),
                        ImageLockMode.WriteOnly,PixelFormat.Format32bppArgb);
                    byte* ppix;
                    int stride = bd.Stride,str;
                    int scan0 = bd.Scan0.ToInt32();
                    for(int j = top;j <= bottom;j++)
                    {
                        str = j * stride;
                        for(int i = left;i <= right;i++)
                        {
                            if(pix.PixelIsTagged(i,j))
                            {
                                ppix = (byte*)(str + 4 * i) + scan0;
                                *ppix = c.B;
                                *(ppix+1) = c.G;
                                *(ppix+2) = c.R;
                                *(ppix+3) = c.A;
                            }
                        }
                    }
                    bmp.UnlockBits(bd);
                }
            }
        }
        public static void Imprint(Bitmap bmp,Color c,PolygonF poly,Rectangle clip)
        {
            if(bmp!=null && poly!=null)
            {
                Rectangle r = poly.GetBoundingRect(0.0f);
                float x,y;
                int left = Math.Max(0,Math.Max(r.Left,clip.Left));
                int right = Math.Min(bmp.Width-1,Math.Min(r.Right,clip.Right));
                int top = Math.Max(0,Math.Max(r.Top,clip.Top));
                int bottom = Math.Min(bmp.Height-1,Math.Min(r.Bottom,clip.Bottom));
                for(int i=left;i<=right;i++)
                    for(int j=top;j<=bottom;j++)
                    {
                        x=(float)i;
                        y=(float)j;
                        if(poly.InPolyNotSwallowed(x,y) > 0)
                            bmp.SetPixel(i,j,c);
                    }
            }
        }
        public static void Imprint(Bitmap bmp,Color c,PixelTagger pix,bool overlay)
        {
            if(bmp!=null && pix!=null)
            {
                int left = Math.Max(pix.Left,0);
                int right = Math.Min(pix.Right,bmp.Width-1);
                int top = Math.Max(pix.Top,0);
                int bottom = Math.Min(pix.Bottom,bmp.Height-1);
                int i,j;

                if(overlay)
                {
                    float p=(float)c.A/255.0f;
                    float q=(float)1.0f-p;
                    Color cb;
                    float pred = p*(float)c.R;
                    float pgreen = p*(float)c.G;
                    float pblue = p*(float)c.B;
                    for(i=left;i<=right;i++)
                    {
                        for(j=top;j<=bottom;j++)
                        {
                            if(pix.PixelIsTagged(i,j))
                            {
                                cb = bmp.GetPixel(i,j);
                                cb = Color.FromArgb(255,
                                    (int)((float)cb.R*q+pred),
                                    (int)((float)cb.G*q+pgreen),
                                    (int)((float)cb.B*q+pblue));
                                bmp.SetPixel(i,j,cb);
                            }
                        }
                    }
                }
                else
                {
                    unsafe
                    {
                        BitmapData bd = bmp.LockBits(new Rectangle(0,0,bmp.Width,bmp.Height),
                            ImageLockMode.WriteOnly,PixelFormat.Format32bppArgb);
                        byte* ppix;
                        int stride = bd.Stride,str;
                        int scan0 = bd.Scan0.ToInt32();
                        for(j = top;j <= bottom;j++)
                        {
                            str = j * stride;
                            for(i = left;i <= right;i++)
                            {
                                if(pix.PixelIsTagged(i,j))
                                {
                                    ppix = (byte*)(str + 4 * i) + scan0;
                                    *ppix = c.B;
                                    *(ppix+1) = c.G;
                                    *(ppix+2) = c.R;
                                    *(ppix+3) = c.A;
                                }
                            }
                        }
                        bmp.UnlockBits(bd);
                    }
                }
            }
        }
        public static void Imprint(Bitmap bmp,Color c,PolygonF poly,bool overlay)
        {
            if(bmp!=null && poly!=null)
            {
                Rectangle r = poly.GetBoundingRect(0.0f);
                float x,y;
                int right = Math.Min(bmp.Width-1,r.Right);
                int bottom = Math.Min(bmp.Height-1,r.Bottom);
                int top = Math.Max(0,r.Top);
                int left = Math.Max(0,r.Left);
                if(overlay)
                {
                    float p=(float)c.A/255.0f;
                    float q= 1.0f-p;
                    Color cb;
                    float pred = p*(float)c.R;
                    float pgreen = p*(float)c.G;
                    float pblue = p*(float)c.B;
                    for(int i=left;i<=right;i++)
                    {
                        for(int j=top;j<=bottom;j++)
                        {
                            x=(float)i;
                            y=(float)j;
                            if(poly.InPolyNotSwallowed(x,y) > 0)
                            {
                                cb = bmp.GetPixel(i,j);
                                cb = Color.FromArgb(cb.A,
                                    (int)((float)cb.R*q+pred),
                                    (int)((float)cb.G*q+pgreen),
                                    (int)((float)cb.B*q+pblue));
                                bmp.SetPixel(i,j,cb);
                            }
                        }
                    }
                }
                else
                {
                    for(int i=left;i<=right;i++)
                    {
                        for(int j=top;j<=bottom;j++)
                        {
                            x=(float)i;
                            y=(float)j;
                            if(poly.InPolyNotSwallowed(x,y) > 0)
                                bmp.SetPixel(i,j,c);
                        }
                    }
                }
            }
        }
        public static void Imprint(Bitmap bmp,Color c,CategoryNode cn,bool overlay)
        {
            if(bmp!=null && cn!=null)
            {
                for(int i=0;i<cn.Sub.Count;i++)
                    Imprint(bmp,c,(CategoryNode)cn.Sub[i],overlay);
                for(int i=0;i<cn.Objects.Count;i++)
                    Imprint(bmp,c,(ParsedObject)cn.Objects[i],overlay);
            }
        }
        public static void Imprint(Bitmap bmp,Color c,ParsedObject od,bool overlay)
        {
            if(bmp!=null && od!=null)
                for(int i=0;i<od.Polygons.Count;i++)
                    Imprint(bmp,c,od.Polygons[i].Pix,overlay);
        }
        /*
        public void cb(object o,Rectangle clip)
        {
            if(o != null)
            {
                CategoryNode cnSel = SelectedCategoryNode;
                CategoryNode cnPix = null;
                if(cnSel!=null)
                    cnPix= cnSel.PixExcludeNode;
                if(o.GetType()==typeof(CategoryNode))
                {
                    CategoryNode cn = (CategoryNode)o;
                    //	Get rid of the objects at the current level.
                    for(int i=0;i<cn.Objects.Count;i++)
                        ClearBitmaps(cn.Objects[i],clip);

                    //	Get rid of the objects in lower level nodes.
                    for(int i=0;i<cn.Sub.Count;i++)
                        ClearBitmaps(cn.Sub[i],clip);
                }
                else if(o.GetType()==typeof(ParsedObject))
                {
                    ParsedObject od = (ParsedObject)o;
                    PolygonF activePoly = SelectedPolygon;
                    int i;
                    if(od == SelectedObject)
                    {
                        for(i=0;i<od.Polygons.Count;i++)
                            if(od.Polygons[i]!=activePoly || this.bViewActiveCat.ImageIndex == 3)
                                Imprint(BmpCurrentObj,Color.Transparent,od.Polygons[i].Pix,clip);
                    }
                    else if(od.Category == cnSel)
                        for(i=0;i<od.Polygons.Count;i++)
                            Imprint(BmpOtherObj,Color.Transparent,od.Polygons[i].Pix,clip);
                    else if(od.Category.PixExcludeNode == Opd.ActiveCategory.PixExcludeNode)
                        for(i=0;i<od.Polygons.Count;i++)
                            Imprint(BmpNonObj,Color.Transparent,od.Polygons[i].Pix,clip);
                }
                else if(o.GetType()==typeof(PolygonF))
                {
                    PolygonF pf = (PolygonF)o;

                    PolygonF activePoly = SelectedPolygon;
                    //	clear active poly when bViewActiveCat is fully selected
                    if(pf != activePoly || this.bViewActiveCat.ImageIndex == 3)
                    {
                        if(pf.Owner == SelectedObject)
                            Imprint(BmpCurrentObj,Color.Transparent,pf.Pix,clip);
                        else if(pf.Owner.Category == cnSel)
                            Imprint(BmpOtherObj,Color.Transparent,pf.Pix,clip);
                        else if(pf.Owner.Category.PixExcludeNode == cnPix)
                            Imprint(BmpNonObj,Color.Transparent,pf.Pix,clip);
                    }
                }
            }
        }
        public void pb(object o,Rectangle clip)
        {
            if(o != null)
            {
                CategoryNode cnSel = SelectedCategoryNode;
                CategoryNode cnPix = null;
                if(cnSel!=null)
                    cnPix= cnSel.PixExcludeNode;
                if(o.GetType()==typeof(CategoryNode))
                {
                    if(o.GetType().Name=="CategoryNode")
                    {
                        CategoryNode cn = (CategoryNode)o;
                        //	Get rid of the objects at the current level.
                        for(int i=0;i<cn.Objects.Count;i++)
                            PaintBitmaps(cn.Objects[i],clip);

                        //	Get rid of the objects in lower level nodes.
                        for(int i=0;i<cn.Sub.Count;i++)
                            PaintBitmaps(cn.Sub[i],clip);
                    }
                }
                else if(o.GetType()==typeof(ParsedObject))
                {
                    ParsedObject od = (ParsedObject)o;
                    PolygonF activePoly = SelectedPolygon;
                    if(od == SelectedObject)
                    {
                        for(int i=0;i<od.Polygons.Count;i++)
                            if(od.Polygons[i]!=activePoly || this.bViewActiveCat.ImageIndex == 3)
                                Imprint(BmpCurrentObj,Opd.ObjCurrColor,od.Polygons[i].Pix,clip);
                    }
                    else if(od.Category == cnSel)
                        for(int i=0;i<od.Polygons.Count;i++)
                            Imprint(BmpOtherObj,Opd.ObjOtherColor,od.Polygons[i].Pix,clip);
                    else if(od.Category.PixExcludeNode == cnPix)
                        for(int i=0;i<od.Polygons.Count;i++)
                            Imprint(BmpNonObj,Opd.ObjNonColor,od.Polygons[i].Pix,clip);
                }
                else if(o.GetType()==typeof(PolygonF) || o.GetType()==typeof(ContourF))
                {
                    PolygonF pf = null;
                    if(o.GetType()==typeof(PolygonF))
                        pf = (PolygonF)o;
                    else
                        pf = ((ContourF)o).PolyOwner;
                    PolygonF activePoly = SelectedPolygon;
                    //	paint active poly when bViewActiveCat is fully selected
                    if(pf != activePoly || this.bViewActiveCat.ImageIndex == 3)
                    {
                        if(pf.Owner == SelectedObject && activePoly != null)
                            Imprint(BmpCurrentObj,Opd.ObjCurrColor,pf.Pix,clip);
                        else if(pf.Owner.Category == cnSel)
                            Imprint(BmpOtherObj,Opd.ObjOtherColor,pf.Pix,clip);
                        else if(pf.Owner.Category.PixExcludeNode == cnPix)
                            Imprint(BmpNonObj,Opd.ObjNonColor,pf.Pix,clip);
                    }
                }
            }
        }
        */
    }
}